// core/Geometry.h

#ifndef _CORE_Geometry_H_
#define _CORE_Geometry_H_

namespace CORE
{
	enum eCorner {
		kLeftTop = 0,
		kRightTop,
		kLeftBottom,
		kRightBottom,
		kTotalCorner,
	};

template <typename T>
class TabiPoint
{
public:
	T		x;
	T		y;

public:
	TabiPoint() : x(0), y(0) {}
	TabiPoint(T x, T y)
	{
		setPoint(x, y);
	}
	TabiPoint(const TabiPoint & other)
	{
		setPoint(other.x, other.y);
	}
	TabiPoint& operator = (const TabiPoint & other)
	{
		setPoint(other.x, other.y);
		return *this;
	}
	bool equals( const TabiPoint& target) const
	{
		return (this->x == target.x) && (this->y == target.y);
	}

	void setPoint(T x, T y)
	{
		this->x = x;
		this->y = y;
	}
};

template <typename T>
class TabiSize
{
public:
	T		width;
	T		height;

public:

	TabiSize() : width(0), height(0) {}
	TabiSize(T width, T height)
	{
		setSize(width, height);
	}
	TabiSize(const TabiSize& other)
	{
		setSize(other.width, other.height);
	}
	TabiSize& operator = (const TabiSize& other)
	{
		setSize(other.width, other.height);
		return (*this);
	}
	bool equals(const TabiSize& target) const
	{
		return (this->width == target.width) && (this->height == target.height);
	}

	void setSize(T width, T height)
	{
		this->width = width;
		this->height = height;
	}
};

template <typename T>
class TabiRect
{
public:
	TabiPoint<T>		point;
	TabiSize<T>			size;


public:
	TabiRect() {}
	TabiRect(T x, T y, T width, T height)
	{
		setRect(x, y, width, height);
	}
	TabiRect(const TabiRect& other)
	{
		point = other.point;
		size = other.size;
	}
	TabiRect& operator = (const TabiRect& other)
	{
		point = other.point;
		size = other.size;
		return (*this);
	}
	void setRect(T x, T y, T width, T height)
	{
		point.x = x;
		point.y = y;
		size.width = width;
		size.height = height;
	}

	TabiPoint<T>	center(void)
	{
		TabiPoint<T> centerPoint;
		centerPoint.x = (T)(point.x + size.width / 2);
		centerPoint.y = (T)(point.y + size.height / 2);
		return centerPoint;
	}

	TabiPoint<T>	maxPoint(void)
	{
		TabiPoint<T> maxPoint;
		maxPoint.x = (T)(point.x + size.width);
		maxPoint.y = (T)(point.y + size.height);
	}

	bool IsContainPoint(const TabiPoint<T> & point) const
	{
		TabiPoint<T> minPoint = this->point;
		TabiPoint<T> maxPoint = maxPoint();

		if (point.x >= minPoint.x 
			&& point.y >= minPoint.y 
			&& point.x <= maxPoint.x;
			&& point.y <= maxPoint.y)
		{
			return true;
		}

		return false;
	}

	bool IsIntersect(const TabiRect<T> & rect) const
	{
		TabiPoint<T> minPoint1 = this->point;
		TabiPoint<T> maxPoint1 = maxPoint();

		TabiPoint<T> minPoint2 = rect->point;
		TabiPoint<T> maxPoint2 = rect.maxPoint();

		return !(maxPoint1.x < minPoint2.x || maxPoint2.x < minPoint1.x
			|| maxPoint1.y < minPoint2.y || maxPoint2.y < minPoint1.y);
	}
};


typedef TabiPoint<int>			iPoint;
typedef TabiSize<int>			iSize;
typedef TabiRect<int>			iRect;
typedef TabiPoint<float>		fPoint;
typedef TabiSize<float>			fSize;
typedef TabiRect<float>			fRect;

};


#endif